package top.lishuoboy.shiro02_springboot_jsp.shiro.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import top.lishuoboy.dependency.base.json.HuJsonUtil;
import top.lishuoboy.shiro02_springboot_jsp.domain.User;
import top.lishuoboy.shiro02_springboot_jsp.mapper.SqlMapper;
import top.lishuoboy.shiro02_springboot_jsp.mapper.UserMapper;
import top.lishuoboy.shiro02_springboot_jsp.shiro.MyByteSource;

/**
 * 多个Realm，实现用户名 + 手机号 均可登录
 * 配置多个realm。导致认证时抛出的异常不细，不抛UnknownAccountException(用户名不存在)、IncorrectCredentialsException(密码错误)，直接抛AuthenticationException（认证异常）
 *
 * @author lishuoboy
 * @date 2022/2/21 23:09
 */
@Slf4j
public class CustomizeMd5RealmTel extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    SqlMapper sqlMapper;

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("== 授权 doGetAuthorizationInfo==================");
        return new SimpleAuthorizationInfo();
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        log.info("== 认证 doGetAuthenticationInfo==================");
        //在token中获取用户名
        String principal = (String) token.getPrincipal();
        Object credentials = token.getCredentials();
        log.debug("用户输入的手机号 principal=={}", principal);
        log.debug("用户输入的密码  credentials=={}", HuJsonUtil.toJsonStr(credentials));
        // 模拟 根据身份信息使用jdbc mybatis查询数据库中的 用户名、1024次的MD5密码/盐 等 用户信息
//        select * from user where name = '#{principal}'
//        User user = new User().setName("zhangsan").setPwd("45c71c907abdbf45044b9e163a9a47d1").setSalt("salt!@#");
        // 真实 根据身份信息使用jdbc mybatis查询数据库中的 用户名、1024次的MD5密码/盐 等 用户信息
        QueryWrapper queryWrapper = new QueryWrapper<User>().eq("tel", principal);
        User user = userMapper.selectOne(queryWrapper);
        log.debug("user=={}", user);

        if (user != null && user.getTel().equals(principal)) {
            //参数1: 数据库用户名  参数2:数据库md5+salt之后的密码  参数3:注册时的随机盐  参数4:realm的名字
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, user.getPwd(), new MyByteSource(user.getSalt()), this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}
